import { Context } from 'koa';
import { AppContext } from '@/types';
import * as response from '@/utils/response';
import { exportToExcel, importFromExcel, generateTemplate, bufferToStream, type ExcelColumn } from '@/utils/excel';
import logger from '@/utils/logger';
import { validate } from '@/utils/validator';
import Joi from 'joi';

/**
 * 通用导入导出控制器
 */
class ExportImportController {
  /**
   * 通用导出接口
   * 前端传入要导出的数据即可
   */
  async export(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;

    const schema = Joi.object({
      filename: Joi.string().required(),
      sheetName: Joi.string().default('Sheet1'),
      columns: Joi.array().items(
        Joi.object({
          header: Joi.string().required(),
          key: Joi.string().required(),
          width: Joi.number().optional(),
        })
      ).required(),
      data: Joi.array().required(),
    });

    const params = await validate<{
      filename: string;
      sheetName: string;
      columns: ExcelColumn[];
      data: any[];
    }>(ctx.request.body as any, schema);

    try {
      const buffer = await exportToExcel({
        filename: params.filename,
        sheetName: params.sheetName,
        columns: params.columns,
        data: params.data,
      });

      ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
      ctx.set('Content-Disposition', `attachment; filename="${params.filename}_${Date.now()}.xlsx"`);
      ctx.body = bufferToStream(buffer);

      logger.info(`导出数据 ${params.data.length} 条 by ${user!.email}`);
    } catch (error) {
      logger.error('导出失败:', error);
      ctx.throw(500, '导出失败');
    }
  }

  /**
   * 通用导入接口
   * 解析Excel并返回数据，由前端处理后续逻辑
   */
  async import(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;
    const file = (ctx.request as any).file;

    if (!file) {
      return response.error(ctx, '请上传Excel文件', 400);
    }

    try {
      const fileBuffer = file.buffer || require('fs').readFileSync(file.path);

      const result = await importFromExcel(fileBuffer);

      if (!result.success) {
        return response.error(ctx, '导入失败', 400, result.errors);
      }

      logger.info(`解析Excel ${result.total} 条数据 by ${user!.email}`);

      // 返回解析后的数据，由前端处理
      response.success(ctx, {
        total: result.total,
        data: result.data,
      }, '解析成功');
    } catch (error) {
      logger.error('导入失败:', error);
      ctx.throw(500, '导入失败');
    }
  }

  /**
   * 下载导入模板
   */
  async downloadTemplate(ctx: Context) {
    const schema = Joi.object({
      filename: Joi.string().required(),
      columns: Joi.array().items(
        Joi.object({
          header: Joi.string().required(),
          key: Joi.string().required(),
          width: Joi.number().optional(),
        })
      ).required(),
      sampleData: Joi.array().optional(),
    });

    const params = await validate<{
      filename: string;
      columns: ExcelColumn[];
      sampleData?: any[];
    }>(ctx.query as any, schema);

    try {
      const buffer = await generateTemplate(params.columns, params.sampleData);

      ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
      ctx.set('Content-Disposition', `attachment; filename="${params.filename}_template.xlsx"`);
      ctx.body = bufferToStream(buffer);
    } catch (error) {
      logger.error('下载模板失败:', error);
      ctx.throw(500, '下载模板失败');
    }
  }
}

export default new ExportImportController();
